+function ($) {
    var Calendar = function (element, options) {
        this.$element = $(element);
        this.options = $.extend({}, options);

        this.initDate()
        this.init()
    }

    Calendar.VERSION = '1.0.0'

    Calendar.TRANSITION_DURATION = 0

    Calendar.prototype.initDate = function () {
        this.year = new Date().getFullYear();
        this.month = new Date().getMonth() + 1;
        this.day = new Date().getDate();
        this.currentDay = new Date().getDate()
        this.currentMonth = new Date().getMonth() + 1
        this.currentYear = new Date().getFullYear()

        if (this.options.year != undefined) {
            this.currentYear = this.options.year;
        }
        if (this.options.month != undefined) {
            this.currentMonth = this.options.month + 1;
        }
        if (this.options.day != undefined) {
            this.currentDay = this.options.day;
        }

        this.firstYear = this.currentYear;
        this.firstMonth = this.currentMonth;
        this.firstDay = this.currentDay;
    }

    Calendar.prototype.init = function () {
        this.initDays(this.currentYear, this.currentMonth)
        this.initMonth(this.currentMonth);
        this.initYear(this.currentYear);
        this.initEvent();

        this.triggerEvent(this);
    }

    Calendar.prototype.reset = function () {
        this.initDate()
        this.init()
    }

    Calendar.prototype.initDays = function (Y, M) {
        var calendar = this;
        var element = this.$element;

        var Temp, i, j
        var FirstDate, MonthDate, CirNum, ErtNum // '当月第一天为星期几,当月的总天数,表格的单元格数及循环数,表格第一排空格数与当月天数之和
        FirstDate = this.GetWeekdayMonthStartsOn(Y, M)// '得到该月的第一天是星期几  0-6
        MonthDate = this.GetDaysInMonth(Y, M)// '得到该月的总天数 30
        ErtNum = FirstDate + MonthDate// -1

        Temp = ""
        if (ErtNum > 35) {
            CirNum = 42
        } else if (ErtNum == 28) {
            CirNum = 28
        } else {
            CirNum = 35
        }
        j = 1

        for (i = 1; i <= CirNum; i++) {
            if (i == 1) {
                Temp += "<table><tr><th>日</th><th>一</th><th>二</th><th>三</th><th>四</th><th>五</th><th>六</th></tr><tr>"
            }
            if (i < FirstDate + 1 || i > ErtNum) {
                Temp += "<td></td>"
            } else {
                if ((j + 1) <= this.currentDay && this.currentMonth == this.firstMonth) {
                    Temp += (this.firstYear == Y && this.firstMonth == M && this.firstDay == j ? "<td class='now'>" : "<td>") + "<a href='javascript:void(0);' val='null'>" + "&nbsp;" + "</a></td>"
                } else {
                    Temp += (this.firstYear == Y && this.firstMonth == M && this.firstDay == j ? "<td class='now'>" : "<td>") + "<a href='javascript:void(0);' val='" + j + "'>" + j + "</a></td>"
                }
                j = j + 1
            }
            if (i % 7 == 0 && i < ErtNum) {
                Temp += "</tr><tr>"
            }
            if (i == CirNum) {
                Temp += "</tr></table>"
            }
        }

        this.$element.find(".allDay").empty();
        this.$element.find(".allDay").append(Temp);
        this.$element.find(".allDay td").on('click', function () {
            var day = $(this).find("a").html();
            if (day != null && day != "&nbsp;") {
                element.find("td").each(function (i) {
                    $(this).removeClass("now");
                });
                $(this).addClass("now");

                calendar.currentDay = $(this).find("a").attr("val");
                calendar.triggerEvent(calendar);
            }
        })
    }

    Calendar.prototype.initMonth = function (month) {
        this.$element.find("div:eq(2)").attr("value", month);
        this.$element.find("div:eq(2)").html(month + "&nbsp;月");
    }

    Calendar.prototype.initYear = function (year) {
        this.$element.find("div:eq(1)").attr("value", year);
        this.$element.find("div:eq(1)").html(year + "&nbsp;年");
    }

    Calendar.prototype.initEvent = function () {
        var calendar = this;

        this.$element.find("div[data-tag='nextMonth']").on('click', function () {
            calendar.nextMonth();
        })

        this.$element.find("div[data-tag='today']").on('click', function () {
            calendar.currentYear = calendar.firstYear;
            calendar.currentMonth = calendar.firstMonth;
            calendar.currentDay = calendar.firstDay;

            calendar.initDays(calendar.firstYear, calendar.firstMonth)
            calendar.initMonth(calendar.firstMonth);
            calendar.initYear(calendar.firstYear);

            calendar.triggerEvent(calendar);
        })
    }

    Calendar.prototype.triggerEvent = function (calendar) {
        var year = calendar.currentYear;
        var month = (calendar.currentMonth + "").length == 1 ? "0" + calendar.currentMonth : calendar.currentMonth;
        var day = (calendar.currentDay + "").length == 1 ? "0" + calendar.currentDay : calendar.currentDay;

        if(calendar.options.dateChanged) calendar.options.dateChanged(String.format("{0}-{1}-{2}", year, month, day));
    }

    Calendar.prototype.nextMonth = function () {
        if (this.currentMonth >= 12) {
            this.currentMonth = 1
            this.currentYear++
        } else {
            this.currentMonth++
        }

        this.initYear(this.currentYear);
        this.initMonth(this.currentMonth);
        this.initDays(this.currentYear, this.currentMonth);
    }

    Calendar.prototype.GetDaysInMonth = function (Y, M) {				//'得到该月的总天数
        if (M == 1 || M == 3 || M == 5 || M == 7 || M == 8 || M == 10 || M == 12)
            return 31;
        else if (M == 4 || M == 6 || M == 9 || M == 11)
            return 30;
        else if (M == 2)
            if ((Y % 4 == 0 && Y % 100 != 0) || (Y % 100 == 0 && Y % 400 == 0))
                return 29;
            else
                return 28;
        else
            return 28;
    }

    Calendar.prototype.GetWeekdayMonthStartsOn = function (Y, M) {		//'得到该月的第一天是星期几
        var date = new Date(Y, M - 1, 1)
        return date.getDay()
    }

    function Plugin(option) {
        return this.each(function () {
            if (option.cache == undefined) {
                option.cache = true
            }
            var $this = $(this)
            var data = $this.data('bs.calendar')
            var options = typeof option == 'object' && option

            if (option.cache) {
                if (!data) $this.data('bs.calendar', (data = new Calendar(this, options)))
            }
            else {
                $this.data('bs.calendar', (data = new Calendar(this, options)))
            }
            if (typeof option == 'string') data[option]()
        })
    }

    var old = $.fn.calendar

    $.fn.calendar = Plugin
    $.fn.calendar.Constructor = Calendar

    // Calendar NO CONFLICT
    // ===============

    $.fn.calendar.noConflict = function () {
        $.fn.calendar = old
        return this
    }
}(jQuery);